package com.good.cardview

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.Gravity
import android.view.View
import android.widget.FrameLayout
import androidx.annotation.NonNull
import androidx.annotation.Nullable
import java.math.BigDecimal
import java.math.MathContext

/**
 * date        ：2020/8/24
 * author      ：蒙景博
 * description ：
 */
class GoodCardView : FrameLayout {

    // 边框半圆弧度半径
    private var mBorderCornerRadius = 8

    // 是否显示左边边框半圆弧度
    private var isShowStartBorderCorner = false
    // 是否显示上边边框半圆弧度
    private var isShowTopBorderCorner = false
    // 是否显示右边边框半圆弧度
    private var isShowEndBorderCorner = false
    // 是否显示下边边框半圆弧度
    private var isShowBottomBorderCorner = false

    // 每个边框半圆之间的间隙
    private var mBorderCornerGap = 1

    // 起始两边半圆数量
    private var mStartOrEndBorderCornerCount = 0
    // 上下两边半圆数量
    private var mTopOrBottomBorderCornerCount = 0

    // 半圆画笔
    private val mBorderCornerPaint by lazy { Paint(Paint.ANTI_ALIAS_FLAG) }

    constructor(@NonNull context: Context) : this(context, null)
    constructor(@NonNull context: Context, @Nullable attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(
        @NonNull context: Context,
        @Nullable attrs: AttributeSet?,
        defStyleAttr: Int
    ) : super(context, attrs, defStyleAttr) {
        initAttribute(attrs, defStyleAttr)
    }

    private fun initAttribute(attrs: AttributeSet?, defStyleAttr: Int) {
        setWillNotDraw(false)
        setLayerType(View.LAYER_TYPE_SOFTWARE, null)
        val mTypeArray = context.obtainStyledAttributes(attrs, R.styleable.GoodCardView, defStyleAttr, 0)
        try {
            mBorderCornerRadius = mTypeArray.getDimensionPixelSize(R.styleable.GoodCardView_cardBorderCornerRadius, mBorderCornerRadius)
            isShowStartBorderCorner = mTypeArray.getBoolean(R.styleable.GoodCardView_cardShowStartBorderCorner, isShowStartBorderCorner)
            isShowTopBorderCorner = mTypeArray.getBoolean(R.styleable.GoodCardView_cardShowTopBorderCorner, isShowTopBorderCorner)
            isShowEndBorderCorner = mTypeArray.getBoolean(R.styleable.GoodCardView_cardShowEndBorderCorner, isShowEndBorderCorner)
            isShowBottomBorderCorner = mTypeArray.getBoolean(R.styleable.GoodCardView_cardShowBottomBorderCorner, isShowBottomBorderCorner)
            mBorderCornerGap = mTypeArray.getDimensionPixelSize(R.styleable.GoodCardView_cardBorderCornerGap, mBorderCornerGap)
        } finally {
            mTypeArray.recycle()
        }
        mBorderCornerPaint.isDither = true
        mBorderCornerPaint.isAntiAlias = true
        mBorderCornerPaint.color = Color.YELLOW
        mBorderCornerPaint.style = Paint.Style.FILL
        mBorderCornerPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        layoutChildren(left, top, right, bottom)
    }

    @SuppressLint("RtlHardcoded")
    private fun layoutChildren(left: Int, top: Int, right: Int, bottom: Int) {
        val parentRight = right - left - paddingEnd
        val parentBottom = bottom - top - paddingBottom
        for (i in 0 until childCount) {
            val childView = getChildAt(i)
            if (childView.visibility != View.GONE) {
                val params = childView.layoutParams as LayoutParams
                val childViewWidth = childView.measuredWidth
                val childViewHeight = childView.measuredHeight
                val gravity = if (params.gravity == -1) Gravity.TOP or Gravity.START else params.gravity
                val absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection)
                val verticalGravity = gravity and Gravity.VERTICAL_GRAVITY_MASK
                val childViewStart = when (absoluteGravity and Gravity.HORIZONTAL_GRAVITY_MASK) {
                    Gravity.CENTER_HORIZONTAL -> paddingLeft + (parentRight - paddingLeft - childViewWidth) / 2 + params.leftMargin - params.rightMargin
                    Gravity.RIGHT -> parentRight - childViewWidth - params.rightMargin - mBorderCornerRadius
                    else -> paddingLeft + params.leftMargin + mBorderCornerRadius
                }
                val childViewTop = when (verticalGravity) {
                    Gravity.TOP -> paddingTop + params.topMargin + mBorderCornerRadius
                    Gravity.CENTER_VERTICAL -> paddingTop + (parentBottom - paddingTop - childViewHeight) / 2 + params.topMargin - params.bottomMargin
                    Gravity.BOTTOM -> parentBottom - childViewHeight - params.bottomMargin - mBorderCornerRadius
                    else -> paddingTop + params.topMargin + mBorderCornerRadius
                }
                childView.layout(childViewStart, childViewTop, childViewStart + childViewWidth, childViewTop + childViewHeight)
            }
        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        calculateSemicircleCount(w, h)
    }

    /**
     * 计算半圆个数
     */
    private fun calculateSemicircleCount(width: Int, height: Int) {
        // 实际绘制半圆数量 = 视图高度或者宽度 / （半圆直径 + 半圆之间的间隙）
        mStartOrEndBorderCornerCount = divides(height.toDouble(), (mBorderCornerGap + (mBorderCornerRadius * 2)).toDouble()).toInt()
        mTopOrBottomBorderCornerCount = divides(width.toDouble(), (mBorderCornerGap + (mBorderCornerRadius * 2)).toDouble()).toInt()
    }

    override fun dispatchDraw(canvas: Canvas?) {
        super.dispatchDraw(canvas)
        canvas?.let {
            if (isShowStartBorderCorner || isShowEndBorderCorner) {
                for (i in 0 until mStartOrEndBorderCornerCount) {
                    // 起始半圆圆心坐标X = 已绘制的 Gap 尺寸 + 已会制的半圆的直径的总尺寸 + 当前将要绘制的半圆半径 + 卡片自身的弧度
                    val mStartOrEndCircleY = ((i + 1) * mBorderCornerGap) + (2 * i * mBorderCornerRadius) + mBorderCornerRadius
                    // start
                    if (isShowStartBorderCorner) {
                        it.drawCircle(0f, mStartOrEndCircleY.toFloat(), mBorderCornerRadius.toFloat(), mBorderCornerPaint)
                    }
                    // end
                    if (isShowEndBorderCorner) {
                        it.drawCircle(measuredWidth.toFloat(), mStartOrEndCircleY.toFloat(), mBorderCornerRadius.toFloat(), mBorderCornerPaint)
                    }
                }
            }
            if (isShowTopBorderCorner || isShowBottomBorderCorner) {
                for (i in 0 until mTopOrBottomBorderCornerCount) {
                    // 上下半圆圆心坐标X = 已绘制的 Gap 尺寸 + 已会制的半圆的直径的总尺寸 + 当前将要绘制的半圆半径 + 卡片自身的弧度
                    val mTopOrBottomCircleX = ((i + 1) * mBorderCornerGap) + (2 * i * mBorderCornerRadius) + mBorderCornerRadius
                    // top
                    if (isShowTopBorderCorner) {
                        it.drawCircle(mTopOrBottomCircleX.toFloat(), 0f, mBorderCornerRadius.toFloat(), mBorderCornerPaint)
                    }
                    // bottom
                    if (isShowBottomBorderCorner) {
                        it.drawCircle(mTopOrBottomCircleX.toFloat(), measuredHeight.toFloat(), mBorderCornerRadius.toFloat(), mBorderCornerPaint)
                    }
                }
            }
        }
    }

    // 使用精度计算，因为 Gap 值可能会很小
    private fun divides(value1: Double, value2: Double): Double {
        return BigDecimal(value1.toString()).divide(BigDecimal(value2.toString()), MathContext.DECIMAL128).toDouble()
    }
}